/*   **********************************************************************  **
 **   Copyright notice                                                       **
 **                                                                          **
 **   (c) 2009, Around(J2)ME				                                 **
 **   All rights reserved.                                                   **
 **                                                                          **
 **   This program and the accompanying materials are made available under   **
 **   the terms of the New BSD License which accompanies this    			 **
 **   distribution.											                 **
 **   A copy is found in the textfile LICENSE.txt							 **
 **                                                                          **
 **   This copyright notice MUST APPEAR in all copies of the file!           **
 **                                                                          **
 **   Main developers:                                                       **
 **     Juri Strumpflohner		http://blog.js-development.com	             **
 **		Matthias Braunhofer		http://matthias.jimdo.com                    **
 **                                                                          **
 **  **********************************************************************  */

package org.aroundme.services;

import java.io.IOException;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.aroundme.model.Place;

/**
 * This class is responsible for adding a new place to the search index
 */
public class Indexer {
	private Directory directory;
	private IndexWriter indexWriter;
	
	public Indexer() {
	}
	
	/**
	 * initializes the Lucene IndexWriter
	 * @throws CorruptIndexException
	 * @throws LockObtainFailedException
	 * @throws IOException
	 */
	public void init(boolean create) throws CorruptIndexException, LockObtainFailedException, IOException {
		Analyzer analyzer = new StandardAnalyzer();
		if (!create) {
			if (IndexReader.isLocked(directory)) {
				IndexReader.unlock(directory);
			}
			indexWriter = new IndexWriter(directory, analyzer, false);
		} else {
			indexWriter = new IndexWriter(directory, analyzer, true);
		}	
	}
	
	/**
	 * writes a new place into the search index or updates an existing place in the search index
	 * @param place
	 * @param isUpdate
	 * @throws CorruptIndexException
	 * @throws IOException
	 */
	public void index(Place place, boolean isUpdate) throws CorruptIndexException, IOException {
		PlaceDocument placeDocument = new PlaceDocument(place);
		if (placeDocument.addFields()) {
			if (isUpdate) {
				indexWriter.updateDocument(createTerm(place.getId()), placeDocument.getDocument());
			} else {
				indexWriter.addDocument(placeDocument.getDocument());
			}
			indexWriter.optimize();
			indexWriter.commit();
		}
	}
	
	/**
	 * removes a place from the search index
	 * @param placeId
	 * @throws IOException 
	 * @throws CorruptIndexException 
	 */
	public void remove(int placeId) throws CorruptIndexException, IOException {
		indexWriter.deleteDocuments(createTerm(placeId));
		indexWriter.optimize();
		indexWriter.commit();
	}
	
	/**
	 * closes the Lucene IndexWriter
	 * @throws CorruptIndexException
	 * @throws IOException
	 */
	public void close() throws CorruptIndexException, IOException {
		indexWriter.close();
	}
	
	/**
	 * creates a term from a certain placeId
	 * @param placeId
	 * @return
	 */
	private Term createTerm(int placeId) {
		return new Term(PlaceDocument.ID, Integer.toString(placeId));
	}

	/* 
	 * Getters and setters
	 */
	public Directory getDirectory() {
		return directory;
	}

	public void setDirectory(Directory directory) {
		this.directory = directory;
	}
}